#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <errno.h>

/**
*       实现场景: 多线程 + 线程同步执行
*/

// 信号量
sem_t   SEM_A_B;
sem_t   SEM_B_C;
sem_t   SEM_C_A;

// 函数指针
typedef void *fFunc(void *arg);

void *funcA(void *arg)
{
    (void)arg;
    pthread_detach(pthread_self());

    sem_wait(&SEM_C_A);
    sem_post(&SEM_A_B);

    printf("run func: %s | line: %d\n", __FUNCTION__, __LINE__);

    while (1)
    {
    }
    return NULL;
}

void *funcB(void *arg)
{
    (void)arg;
    pthread_detach(pthread_self());

    sem_wait(&SEM_A_B);
    sem_post(&SEM_B_C);     // 信号量+1

    printf("func: %s | line: %d\n", __FUNCTION__, __LINE__);
    while (1)
    {
    }
    return NULL;
}

void *funcC(void *arg)
{
    (void)arg;
    pthread_detach(pthread_self());

    sem_wait(&SEM_B_C);     // 信号量-1，为0接触阻塞, 大于0程序往下执行
    sem_post(&SEM_C_A);

    printf("func: %s | line: %d\n", __FUNCTION__, __LINE__);
    while (1)
    {
    }
    return NULL;
}


int main(void)
{
    // 初始化信号量
    sem_init(&SEM_A_B, 0, 0);
    sem_init(&SEM_B_C, 0, 0);
    sem_init(&SEM_C_A, 0, 1);       // 初始化信号量的值为1,表示表示该可以进行自减一操作，直接跳过阻塞

    // 初始化函数指针
    fFunc *pFunc;

    pthread_t Thread_A;
    pthread_t Thread_B;
    pthread_t Thread_C;

    pFunc = funcA;
    printf("pFunc: %p\n", pFunc);
    if ( 0 != pthread_create(&Thread_A, NULL ,pFunc, NULL) )
    {
        printf("error: %s\n", strerror(errno));
    }

    pFunc = funcB;
    printf("pFunc: %p\n", pFunc);
    if ( 0 != pthread_create(&Thread_B, NULL ,pFunc, NULL) )
    {
        printf("error: %s\n", strerror(errno));
    }

    pFunc = funcC;
    printf("pFunc: %p\n", pFunc);
    if ( 0 != pthread_create(&Thread_C, NULL ,pFunc, NULL) )
    {
        printf("error: %s\n", strerror(errno));
    }

    pthread_join(Thread_A, NULL);
    pthread_join(Thread_B, NULL);
    pthread_join(Thread_C, NULL);

    sem_destroy(&SEM_A_B);
    sem_destroy(&SEM_B_C);
    sem_destroy(&SEM_C_A);
    return 0;
}
